import json
import os
import traceback
from glob import glob

import zhconv
from colorama import Fore

from console_py import console
from poetry import constants
from poetry.constants import Sql
from poetry.db import DBConfig


class PoetryDataProcessor:

    def __init__(self):
        self.console = console.Console()
        self.fields = {
            "author": {"type": "string"},
            "author_id": {"type": "int"},
            "dynasty": {"type": "string"},
            "title": {"type": "string"},
            "rhythmic": {"type": "string"},
            "chapter": {"type": "string"},
            # "paragraphs": {"type": "json"},
            "notes": {"type": "json"},
            "collection": {"type": "string"},
            "section": {"type": "string"},
            "content": {"type": "json"},
            "comment": {"type": "json"},
            "tags": {"type": "json"},
        }
        self.console.logPath = "./log.txt"
        self.import_poetry = ImportPoetry()
        self.db = DBConfig(db_type='remote')

    # 将json文件录入mysql数据库
    def importData(self, db: DBConfig, source: str, table: str, info: dict):
        path = info["path"]
        dynasty = info["dynasty"]
        collection = info["collection"]
        author = info.get("author")
        if isinstance(path, str):
            names = list(glob(f"{source}/{path}"))
        else:
            names = []
            for v in path:
                names += list(glob(f"{source}/{v}"))
        self.console.log()
        begin = self.console.info(f"正在处理  {collection}")
        success = 0
        error = 0
        for name in names:
            filename = os.path.basename(name)
            relName = os.path.relpath(name, source)
            try:
                self.console.log(f"正在处理文件  {relName}")
                file = open(name, "r", encoding="utf-8")
                # 繁体转简体
                data = json.loads(zhconv.convert(file.read(), 'zh-cn'))
                if filename == "tangshisanbaishou.json":
                    data = self.shisanbai(data)
                if not isinstance(data, list):
                    data = [data]
                for poet in data:
                    values = []
                    content_is_valid = True
                    for field in self.fields:
                        if self.fields[field]["type"] == "string":
                            value = poet.get(field, "")
                            if field == "collection":
                                value = collection
                            elif field == "dynasty":
                                value = dynasty
                            elif field == "author":
                                if author:
                                    value = author
                                if not value:
                                    value = "不詳"
                            values.append(value)
                        elif field == "content":
                            value = poet.get(field, None)
                            if not value:
                                value = poet.get('paragraphs', None)
                            if not value:
                                value = poet.get('para', None)
                            if not value:
                                content_is_valid = False
                            values.append(json.dumps(value, ensure_ascii=False))
                        else:
                            value = poet.get(field, None)
                            if field == "tags":
                                if not isinstance(value, list):
                                    try:
                                        value = [value]
                                    except Exception:
                                        value = []
                                # if collection not in value:
                                #     value.append(collection)
                            elif field == 'author_id':
                                value = -1
                            values.append(json.dumps(value, ensure_ascii=False))
                    if not content_is_valid:
                        print('内容为空，忽略......')
                        continue
                    # 处理 null 字符串
                    processed_values = [
                        None if isinstance(v, str) and v.strip().lower() in {'null', '[null]'} else v
                        for v in values
                    ]
                    params = [None] + processed_values
                    num_placeholders = len(self.fields) + 1
                    sql = f"INSERT INTO `{table}` VALUES ({', '.join(['%s'] * num_placeholders)})"
                    db.execute(sql, params)
                    success += 1
            except Exception:
                self.console.error(traceback.format_exc())
                end = self.console.error(f"{relName}  处理出错")
                error += 1
        if error == 0:
            end = self.console.success(f"{collection}  处理完毕", begin)
        else:
            end = self.console.warning(f"{collection}  处理完毕，共有{error}个错误", begin)
        self.console.log()
        return {
            "collection": collection,
            "count": success,
            "time": f"{self.console.round(end - begin)}s",
        }

    # 录入作者
    def importAuthors(self,
                      db: DBConfig,
                      source: str,
                      table: str,
                      paths: list[str],
                      ):
        names = ()
        for path in paths:
            names += tuple(glob(f"{source}/{path}"))
        self.console.log()
        begin = self.console.log("正在处理  作者", Fore.CYAN)
        success = 0
        error = 0
        for name in names:
            name = os.path.normpath(name)
            relName = os.path.relpath(name, source)
            try:
                self.console.log(f"正在处理文件  {relName}")
                file = open(name, "r", encoding="utf-8")
                data = json.loads(zhconv.convert(file.read(), 'zh-cn'))
                if type(data).__name__ != "list":
                    data = [data]
                for author in data:
                    sql = f"INSERT INTO `{table}` VALUES (null,%s,%s,%s)"
                    db.execute(
                        sql,
                        (
                            author.get("name") or "",
                            author.get("desc") or author.get("description") or "",
                            author.get("short_description") or "",
                        ),
                    )
                    success += 1
            except Exception:
                self.console.error(traceback.format_exc())
                self.console.error(f"{relName}  处理出错")
                error += 1
        if error == 0:
            end = self.console.success("作者  处理完毕", begin)
        else:
            end = self.console.warning(f"作者  处理完毕，共有{error}个错误", begin)
        self.console.log()
        return {
            "collection": "作者",
            "count": success,
            "time": f"{self.console.round(end - begin)}s",
        }

    # 特殊处理唐诗三百首
    def shisanbai(self, data: dict):
        content = data["content"]
        data["dynasty"] = "唐"
        result: list[dict] = []
        for group in content:
            for poet in group["content"]:
                if poet["subchapter"]:
                    poet["title"] = poet["subchapter"]
                else:
                    poet["title"] = poet["chapter"]
                del poet["chapter"]
                del poet["subchapter"]
                poet["tags"] = ["唐诗三百首", group["type"]]
                result.append(poet)
        return result

    def start_data_transform(self):
        begin = self.console.log("开始处理文件", Fore.CYAN)

        # 获取各种参数
        configFile = open("./config.json", "r", encoding="utf-8")
        config = json.loads(configFile.read())
        table = config["table"]
        tableAuthor = config["tableAuthor"]
        source = config["source"]
        data = config["files"]["data"]
        include = config["files"]["include"]
        exclude = config["files"]["exclude"]
        authors = config["files"]["authors"]

        # 删除旧表, 创建新表
        # 诗词表
        if len(table):
            self.db.execute(Sql.create_poetry_table_sql)
        # 作者表
        if len(tableAuthor):
            self.db.execute(Sql.create_poetry_author_table_sql)

        # 循环处理json文件
        arr = []
        maxLenCollection = 0
        maxLenTime = 0
        total = 0
        res = None
        hasInclude = len(include) > 0
        hasExclude = len(exclude) > 0
        if len(table):
            for info in data:
                if hasInclude and info["collection"] not in include:
                    continue
                if hasExclude and info["collection"] in exclude:
                    continue
                res = self.import_poetry.importData(self.db, source, table, info)
                arr.append(res)
                maxLenCollection = max(maxLenCollection, console.strLen(res["collection"]))
                maxLenTime = max(maxLenTime, console.strLen(res["time"]))
                if isinstance(res["count"], int):
                    total += res["count"]
        if len(tableAuthor):
            if isinstance(authors, str):
                authors = [authors]
            res = self.import_poetry.importAuthors(self.db, source, tableAuthor, authors)
            arr.append(res)
            maxLenCollection = max(maxLenCollection, console.strLen(res["collection"]))
            maxLenTime = max(maxLenTime, console.strLen(res["time"]))
            if isinstance(res["count"], int):
                total += res["count"]

        self.console.log('开始匹配作者信息')
        update_author_sql = """update chinese_poetry p set author_id = (select id from chinese_poetry_author pa where pa.name=p.author limit 1)"""
        self.db.execute(update_author_sql)
        self.console.log('匹配作者信息成功')

        self.console.log('开始初始化其他表信息')
        self.db.execute(constants.Sql.create_favorite_sql)
        self.db.execute(constants.Sql.create_poetry_access_history_sql)
        self.db.execute(constants.Sql.create_poetry_type_sql)
        self.db.execute(constants.Sql.import_poetry_type_sql)
        self.db.execute(constants.Sql.create_social_auth_sql)
        self.db.execute(constants.Sql.create_user_info_sql)
        self.console.log('初始化其他表信息成功')

        # 最后输出统计信息
        end = self.console.log("所有文件处理完毕", Fore.GREEN, begin)
        self.console.log()
        for v in arr:
            collection = self.console.strAlign(v["collection"], maxLenCollection, "L")
            time = self.console.strAlign(v["time"], maxLenTime, "L")
            self.console.log(f"{collection}  用时：{time}  记录数：{v['count']}")
        self.console.log(f"共计用时：{self.console.round(end - begin)}s")
        self.console.log(f"记录总数：{total}")
        self.console.log()